/*
 * Copyright 2012 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package edu.scu.sculijobs.server;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.google.android.gcm.server.Message;
import com.google.android.gcm.server.Result;
import com.google.android.gcm.server.Sender;
import java.util.Comparator;
import com.google.code.linkedinapi.client.LinkedInApiClient;
import com.google.code.linkedinapi.client.LinkedInApiClientFactory;
import com.google.code.linkedinapi.client.oauth.LinkedInAccessToken;
import com.google.code.linkedinapi.client.enumeration.JobField;
import com.google.code.linkedinapi.client.enumeration.SearchParameter;
import com.google.code.linkedinapi.schema.Job;
import com.google.code.linkedinapi.schema.Jobs;

@SuppressWarnings("serial")
public class SearchServlet extends BaseServlet {

  private Sender sender;
  private static final Logger log = Logger.getLogger(SearchServlet.class.getName());
  private static int LIMIT = 10;
  private static int DAY_FROM_NOW = -30;
  private static final String CONSUMER_KEY = "45vjs1mpz5il";
  private static final String CONSUMER_SECRET = "03yYik0uZ7lHkWfS";
	
  private Hashtable<String,List<String>> cacheJobs;
  @Override
  public void init(ServletConfig config) throws ServletException {
    super.init(config);
    cacheJobs = new Hashtable<String,List<String>> ();
    sender = newSender(config);
  }
  
  /**
   * Creates the {@link Sender} based on the servlet settings.
   */
  protected Sender newSender(ServletConfig config) {
    String key = (String) config.getServletContext()
        .getAttribute(ApiKeyInitializer.ATTRIBUTE_ACCESS_KEY);
    return new Sender(key);
  }

  @Override
  protected void doGet(HttpServletRequest req, HttpServletResponse resp)
      throws IOException {
    resp.setContentType("text/html");
    PrintWriter out = resp.getWriter();
    out.print("<html><body>");
    
    String reset = req.getParameter("reset");
    String debug = req.getParameter("debug");
    
    if("true".equals(reset)) {
    	cacheJobs.clear();
    	return;
    } else if("true".equals(debug)) {
    	cacheJobs.clear();
    }
    List<NotificationSettings> listNotificationSettings = Dao.INSTANCE.listNotificationSettingss();
    for(NotificationSettings notificationSettings : listNotificationSettings)
    {
    	
//    	String CONSUMER_KEY = "aua0fv43rz1w";
//    	String CONSUMER_SECRET = "WwJxhr93mYGLOpN3";

//    	String liToken = "7a62540c-101a-4ce2-82e4-95de98f5ce6d";//notificationSettings.getLiToken();
//    	String liTokenSecret = "390bd58d-2d2f-405e-9d92-c9bd68da6ef5";//notificationSettings.getLiTokenSecret();
//    	
    	String liToken = notificationSettings.getLiToken();
    	String liTokenSecret = notificationSettings.getLiTokenSecret();
    	
    	LinkedInApiClientFactory factory   = LinkedInApiClientFactory.newInstance(CONSUMER_KEY, CONSUMER_SECRET);
    	LinkedInAccessToken accessToken = new LinkedInAccessToken(liToken, liTokenSecret);
    	LinkedInApiClient client = factory.createLinkedInApiClient(accessToken);
    	
    	String companies = notificationSettings.getCompanies();
    	List<Job> jobList = new ArrayList<Job>();
    	if(companies.isEmpty()) {
    		Map<SearchParameter,String> searchParameterMap = new HashMap<SearchParameter,String>();
        	searchParameterMap.put(SearchParameter.JOB_TITLE, notificationSettings.getJobTitle());
        	
    		//If no company, then dont define the comapnies
    		searchParameterMap.put(SearchParameter.POSTAL_CODE, notificationSettings.getZipcode());
        	searchParameterMap.put(SearchParameter.COUNTRY_CODE, "us");
        	searchParameterMap.put(SearchParameter.DISTANCE, "100");
        	
        	Jobs jobs = client.searchJobs(searchParameterMap, EnumSet.allOf(JobField.class),0,50);
        	try {
        		jobList = jobs.getJobList();
        	} catch(Exception e) {
        		e.printStackTrace();
        	}
        	
    	} else {
    		String[] companiesArray = companies.split(",");
    		jobList = new ArrayList<Job>();
    		for(String company: companiesArray) {
    			Map<SearchParameter,String> searchParameterMap = new HashMap<SearchParameter,String>();
            	searchParameterMap.put(SearchParameter.JOB_TITLE, notificationSettings.getJobTitle());
            	searchParameterMap.put(SearchParameter.POSTAL_CODE, notificationSettings.getZipcode());
            	searchParameterMap.put(SearchParameter.COUNTRY_CODE, "us");
            	searchParameterMap.put(SearchParameter.DISTANCE, "100");
            	searchParameterMap.put(SearchParameter.COMPANY_NAME, company);
            	
            	Jobs jobs = client.searchJobs(searchParameterMap, EnumSet.allOf(JobField.class),0,50);
            	List<Job> eachCompanyJobs = jobs.getJobList();
            	if(eachCompanyJobs != null && !eachCompanyJobs.isEmpty()) {
            		jobList.addAll(eachCompanyJobs);
            	}
    			
    		}
    		
    	}
    
    	Collections.sort(jobList,new Comparator<Job>() {

			@Override
			public int compare(Job o1, Job o2) {
				// TODO Auto-generated method stub
				return o2.getPostingTimestamp().compareTo(o1.getPostingTimestamp());
			}
		});
    	
    	
    	
    
    	Calendar lookForNewJobCal =  Calendar.getInstance();
    	lookForNewJobCal.add(Calendar.DATE, DAY_FROM_NOW);
    	Date lookForNewJobDate = lookForNewJobCal.getTime();
    	
    	
    	StringBuilder jobIds = new StringBuilder();
    	int newJobCounter = 0;
    	String userId = new Long(notificationSettings.getId()).toString();
    	for(int i = 0; i < LIMIT && i < jobList.size(); i++) {
    		Job job = jobList.get(i);
    		
    		List<String> cacheJobIdList = cacheJobs.get(userId);
    		
    		if(cacheJobIdList == null) {
    			cacheJobIdList = new ArrayList<String>();
    			cacheJobs.put(userId,cacheJobIdList);
    		}
    		Date postingDate = new Date(job.getPostingTimestamp());
    		boolean newJobFound = !cacheJobIdList.contains(userId) && postingDate.after(lookForNewJobDate);
    		if(newJobFound) {
    			String jobStr = job.getId() + "," + job.getPosition().getTitle() + "[" + job.getCompany().getName() + "]";
        		out.println(jobStr + "<BR>");
        		out.println("PostDate:" + new Date(job.getPostingTimestamp())+ "<BR>");
        		if(newJobCounter != 0) {
        			jobIds.append(",");
        		} 
        		jobIds.append(job.getId());
        		
                
                cacheJobIdList.add(job.getId());
                newJobCounter++;
    		}
    		
    		
    		
    	}
    	if(!jobIds.toString().isEmpty()) {
    		String registrationId = notificationSettings.getDeviceid();
            
    		sendGCMMessage(jobIds.toString(), registrationId);
    	}
    }

    out.print("</body></html>");
    resp.setStatus(HttpServletResponse.SC_OK);
  }

  
  
  
  private void sendGCMMessage(String jobIds, String registrationId) throws IOException {
	Message message = new Message.Builder().addData("jobIDs", jobIds).build();
	Result result = sender.send(message, registrationId, 5);
	log.info("Result of sending message to " + registrationId + "=" + result);
  }

  @Override
  protected void doPost(HttpServletRequest req, HttpServletResponse resp)
      throws IOException {
    doGet(req, resp);
  }
}
